import pymysql
import yaml
"""
1.PyMySQL 是一个第三方库，安装PyMySQL: 1.pip install pymysql; 2.通过pycharm 【Setting】-【Project】安装;
2.导入 import pymysql
3.创建数据库的链接 connect = pymysql.connect() 参数：host 数据库主机地址，port 数据库端口号(int类型)，user 登录账号，
password 登录密码，database 要连接的数据库名称，charset 数据库编码格式(utf8)
4.基于上述connect对象创建cursor游标，connect.cursor(),游标的理解：可以把作为数据数据操作的对外暴露的服务接口，承载了行为和数据；
5.基于游标执行sql, cursor.execute(sql);
6.执行完查询的sql后获取查询到的数据datas = cursor.fetchall() 默认返回的是元组数据类型；
7.所有操作执行完毕不需要在进行数据库的操作了要关闭游标cursor.close(),并关闭数据库连接connect.close()
8.由于查询操作返回的是数据类型默认是元组，对数据的获取并不方便，所以我们可以指定游标返回字典数据类型；
9.在创建游标时传入pymysql.cursors.DictCursor，即：connect.cursor(pymysql.cursors.DictCursor) 实现指定返回字典数据类型
10.对数据库进行增/删/改操作,需要进行事务的提交 connect.commit(), 查询操作无需此操作；
11. 封装成一个工具类实现在其他模块中调用，完成数据增删改查操作；

"""



# 使用 pymysql 连接指定的数据库
# connect = pymysql.connect(host="47.103.126.208",   # 数据库主机地址
#                           port=3306,  # 数据库端口号
#                           user="siyuan",  # 登录账号
#                           password="123456", # 登录密码
#                           database="mall",  # 要访问的数据库名称
#                           charset="utf8")   # 数据库编码格式"utf8"
#
# # 创建数据库的游标（可以理解为对数据进行增删改查的对外服务的接口，承载操作行为的）
# cursor = connect.cursor(pymysql.cursors.DictCursor) # pymysql.cursors.DictCursor 指定以字典的形式返回查询到的数据
# # 在游标中执行sql
# sql = 'SELECT * FROM `ls_user` WHERE id in (1,2,3,4,5,6,7,8,9,10);'
# cursor.execute(sql)
# # 获取游标执行sql后返回的查询数据 fetone()-> 只返回一条匹配到的数据
# datas = cursor.fetchall()
# print(datas)   # (('xx','xx',...),)
# print(type(datas))
# cursor.close() # 操作执行完毕不需要在执行其他操作了需要关闭游标
# connect.close() # 关闭数据库链接
# siyuan_data = datas[0]
# 如何判断查询出来的数据有多少条？
# data_nums = len(datas)
# print(data_nums)
# for db_data in datas:
#     print(db_data)
# 练习：通过pymysql查询nickname="自己的账号的数据"并把获取到的数据打印出来
# 练习：通过pymysql.cursors.DictCursor指定游标的返回数据为字典，获取查询到的mobile的值（比如取第一个条数据的mobile值）
# mobile = datas[0].get("mobile")
# print(mobile)
# 练习：查询出userid 1-10的用户的信息，并把该些用户的手机号，存入一个list中并print该List
# mobile_list = []  # 创建一个空列表作为数据容器，用于存放查询到的mobile
# for user_data in datas:
#     mobile = user_data.get("mobile")
#     mobile_list.append(mobile)
# print(mobile_list)

# mobile_list = [user_data.get("mobile") for user_data in datas]
# print(mobile_list)

# # 创建数据库链接
# connect = pymysql.connect(host="47.103.126.208", port=3306, user="siyuan", password="123456", database="studentsDB", charset='utf8')
# # 创建游标cursor
# cursor = connect.cursor(pymysql.cursors.DictCursor)  # 默认返回的是元组，如果要返回字典传入pymysql.cursors.DictCursor
# # 执行update 的 sql
# #sql = "UPDATE automation25 SET name='思源6666666' WHERE id=4;"
# # 执行INSERT 的 sql
# #sql = "INSERT INTO automation25(id, name) VALUES (10001,'思源10001');"
# # 执行 DELETE 的 sql
# sql = "DELETE FROM automation25 WHERE id = 10001;"
# cursor.execute(sql)
# # 需要提交事务（涉及的增/删/改的操作要进行事务提交）
# connect.commit()  # 注意操作对象是connect 非cursor
# cursor.close()
# connect.close()
#练习：
# 1.通过pymysql INSERT一条数据包含id,name
# 2.对INSERT的数据进行UPDATE 修改对应ID的name;
# 3.把这条数据进行删除操作；

class BaseDB:
    """
    通过创建BaseDB实例实现对数据库的增删改查
    用法示例：
    1.创建实例 db=BaseDB();
    2.查询操作：res = db("select", 查询的sql)
    3.更改数据操作：db("update", 修改的sql)
    4.不需要再执行数据库操作时需要释放资源执行：db(connect=False)
    注意：执行db(connect=False)以后，需要重新创建db实例后才能执行数据库的增删改查；
    """

    def __init__(self):
        # 读取config.yaml中的数据，获取数据库连接信息
        with open("./config.yaml", "r", encoding="UTF-8") as f:
            config_datas = yaml.safe_load(f)
        db_config_data = config_datas.get("db_data")
        # 创建数据库链接
        self.connect = pymysql.connect(**db_config_data)

    # 查询数据
    def select_datas(self, sql):
        # 创建游标
        cursor = self.connect.cursor(pymysql.cursors.DictCursor)
        # 执行sql
        cursor.execute(sql)
        # 获取查询结果
        select_data = cursor.fetchall()
        cursor.close()
        return select_data

    # 修改数据
    def charge_datas(self, sql):
        # 创建游标
        cursor = self.connect.cursor(pymysql.cursors.DictCursor)
        # 执行 sql
        cursor.execute(sql)
        # 提交事务
        self.connect.commit()
        cursor.close()

    # 关闭数据库连接
    def close_db_connect(self):
        self.connect.close()

    # 总入口
    def __call__(self, act=None, sql=None, connect=True):
        if connect:
            if act in ['select', 'SELECT']:
                data = self.select_datas(sql)
                return data
            elif act in ["UPDATE", "update", "INSERT", "insert", "DELETE", "delete"]:
                self.charge_datas(sql)
        else:
            self.close_db_connect()


if __name__ == '__main__':

    # db = BaseDB()
    # sql = "SELECT * FROM automation25;"
    # res = db("select", sql)
    # print(res)
    # sql2 = "UPDATE automation25 SET name='思源6666667' WHERE id=4;"
    # db("update", sql2)
    # db(connect=False)  # 关闭数据库的连接
    # 练习：通过BaseDB的封装，实现数据的查询，查询完毕关闭数据库的连接
    # db = BaseDB()
    # # 查询
    # db("select", "select * from ls_user")  # 此时会执行魔法方法__call__中的代码
    # # 更改数据库的数据
    # db("update", "update ls_user set nick_name='Jie' where id=1")
    # db(connect=False)
    # db = BaseDB()
    # # 查询ls_user表中的所有用户的电话
    # sql = "select mobile from ls_user"
    # db_users = db("select", sql)
    # print(db_users)
    # mobiles_list = []
    # for mobile_dict in db_users:
    #     mobile = mobile_dict.get("mobile")
    #     mobiles_list.append(mobile)
    # db(connect=False)
    # print(mobiles_list)
    pass


